/**
  ******************************************************************************
  * @file    sensor_service.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    04-July-2014
  * @brief   Add a sample service using a vendor specific profile.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
#include "sensor_service.h"
#include "stm32_bluenrg_ble.h"
/* Private variables ---------------------------------------------------------*/
const char *name = "BlueNRG";
uint8_t bdaddr[6] = {0x12, 0x34, 0x00, 0xE1, 0x80, 0x07};
extern SPI_HandleTypeDef SpiHandle;
uint8_t bnrg_expansion_board = IDB05A1;
volatile int connected = FALSE;
volatile uint8_t set_connectable = 1;
volatile uint16_t connection_handle = 0;
volatile uint8_t notification_enabled = FALSE;
uint16_t sampleServHandle, TXCharHandle, RXCharHandle;
uint16_t accServHandle, freeFallCharHandle, accCharHandle;
uint16_t service_handle, dev_name_char_handle, appearance_char_handle;
/* Private functions ---------------------------------------------------------*/
static void bluenrg_set_address(uint8_t* bdaddr);
static void bluenrg_gatt_gap_init(void);

/**
 * @}
 */

/** @defgroup SENSOR_SERVICE_Private_Macros
 * @{
 */
/* Private macros ------------------------------------------------------------*/

/* Store Value into a buffer in Little Endian Format */
#define STORE_LE_16(buf, val)    ( ((buf)[0] =  (uint8_t) (val)    ) , \
                                   ((buf)[1] =  (uint8_t) (val>>8) ) )

tBleStatus bluenrg_init(uint8_t* bdaddr)
{
    bluenrg_set_address(bdaddr);
    bluenrg_gatt_gap_init();
    aci_hal_set_tx_power_level(1,7);
 
    return BLE_STATUS_SUCCESS;
}

static void bluenrg_set_address(uint8_t* bdaddr)
{
    uint8_t write_config_data_mode = 0x02;
    if(aci_hal_write_config_data(0x2D, 0x01, &write_config_data_mode) != BLE_STATUS_SUCCESS)
        while(1);
   
    if(aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET, CONFIG_DATA_PUBADDR_LEN, bdaddr) != BLE_STATUS_SUCCESS)
        while(1);
}

static void bluenrg_gatt_gap_init(void)
{
    if(aci_gatt_init() != BLE_STATUS_SUCCESS)
        while(1);
    if(aci_gap_init_IDB05A1(GAP_PERIPHERAL_ROLE_IDB05A1, 0, 0x07, &service_handle, &dev_name_char_handle, &appearance_char_handle) != BLE_STATUS_SUCCESS)
        while(1);
   

}

void setConnectable(void)
{  
  
  const char local_name[] = {AD_TYPE_COMPLETE_LOCAL_NAME,'B','l','u','e','N','R','G'};
  
  /* disable scan response */
  hci_le_set_scan_resp_data(0,NULL);
  
  if(aci_gap_set_discoverable(ADV_IND, 100, 100, PUBLIC_ADDR, NO_WHITE_LIST_USE,
                                 sizeof(local_name), local_name, 0, NULL, 0, 0) != BLE_STATUS_SUCCESS)
      while(1);
                                 
  if(bluenrg_delete_adv_type(AD_TYPE_COMPLETE_LOCAL_NAME) != BLE_STATUS_SUCCESS)
      while(1);
 
  if(bluenrg_delete_adv_type(AD_TYPE_TX_POWER_LEVEL) != BLE_STATUS_SUCCESS)
      while(1);
}

tBleStatus bluenrg_delete_adv_type(uint8_t data)
{
    if(aci_gap_delete_ad_type(data) != BLE_STATUS_SUCCESS)
         return BLE_STATUS_ERROR;
    
    return BLE_STATUS_SUCCESS;
         
}

tBleStatus bluenrg_stop_adv(void)
{
    
    if(aci_gap_set_non_discoverable()!= BLE_STATUS_SUCCESS)
         return BLE_STATUS_ERROR;
    
    return BLE_STATUS_SUCCESS;
}

tBleStatus bluenrg_adv_manufacture_data(uint8_t* data, uint8_t len)
{
     if(aci_gap_set_discoverable(ADV_IND, 100, 100, PUBLIC_ADDR, NO_WHITE_LIST_USE,
                                 len-1, (const char*)(data+1), 0, NULL, 0, 0) != BLE_STATUS_SUCCESS)
      while(1);
                         
    if(bluenrg_delete_adv_type(AD_TYPE_TX_POWER_LEVEL) != BLE_STATUS_SUCCESS)
      while(1);
    
    return BLE_STATUS_SUCCESS;
}

void bluenrg_update_adv(void* data)
{
    if(aci_gap_update_adv_data(0x04, data) != BLE_STATUS_SUCCESS)
        while(1);
}

void bluenrg_io_init(void)
{
     /* Initialize the BlueNRG SPI driver */
    BNRG_SPI_Init();
    /* Initialize the BlueNRG HCI */
    HCI_Init();
}

void bluenrg_start_work(void)
{
    /* Reset BlueNRG hardware */
    BlueNRG_RST();
    /*init bluenrg*/
    bluenrg_init(bdaddr); 
    HCI_Process();
}

/**
 * @brief  This function is called when there is a LE Connection Complete event.
 * @param  uint8_t Address of peer device
 * @param  uint16_t Connection handle
 * @retval None
 */
void GAP_ConnectionComplete_CB(uint8_t addr[6], uint16_t handle)
{  
  connected = TRUE;
  connection_handle = handle;
  
  PRINTF("Connected to device:");
  for(int i = 5; i > 0; i--){
    PRINTF("%02X-", addr[i]);
  }
  PRINTF("%02X\n", addr[0]);
}

/**
 * @brief  This function is called when the peer device gets disconnected.
 * @param  None 
 * @retval None
 */
void GAP_DisconnectionComplete_CB(void)
{
  connected = FALSE;
  PRINTF("Disconnected\n");
  /* Make the device connectable again. */
  set_connectable = TRUE;
  notification_enabled = FALSE;
}

/**
 * @brief  Read request callback.
 * @param  uint16_t Handle of the attribute
 * @retval None
 */
void Read_Request_CB(uint16_t handle)
{  

  //EXIT:
  if(connection_handle != 0)
    aci_gatt_allow_read(connection_handle);
}

/**
 * @brief  Callback processing the ACI events.
 * @note   Inside this function each event must be identified and correctly
 *         parsed.
 * @param  void* Pointer to the ACI packet
 * @retval None
 */
void HCI_Event_CB(void *pckt)
{
  hci_uart_pckt *hci_pckt = pckt;
  /* obtain event packet */
  hci_event_pckt *event_pckt = (hci_event_pckt*)hci_pckt->data;
  
  if(hci_pckt->type != HCI_EVENT_PKT)
    return;
  
  switch(event_pckt->evt){
    
  case EVT_DISCONN_COMPLETE:
    {
      GAP_DisconnectionComplete_CB();
    }
    break;
    
  case EVT_LE_META_EVENT:
    {
      evt_le_meta_event *evt = (void *)event_pckt->data;
      
      switch(evt->subevent){
      case EVT_LE_CONN_COMPLETE:
        {
          evt_le_connection_complete *cc = (void *)evt->data;
          GAP_ConnectionComplete_CB(cc->peer_bdaddr, cc->handle);
        }
        break;
      }
    }
    break;
    
  case EVT_VENDOR:
    {
      evt_blue_aci *blue_evt = (void*)event_pckt->data;
      switch(blue_evt->ecode){

      case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:         
        {
          /* this callback is invoked when a GATT attribute is modified
          extract callback data and pass to suitable handler function */
            evt_gatt_attr_modified_IDB05A1 *evt = (evt_gatt_attr_modified_IDB05A1*)blue_evt->data;
            Attribute_Modified_CB(evt->attr_handle, evt->data_length, evt->att_data); 
                           
        }
        break; 

      case EVT_BLUE_GATT_READ_PERMIT_REQ:
        {
          evt_gatt_read_permit_req *pr = (void*)blue_evt->data;                    
          Read_Request_CB(pr->attr_handle);                    
        }
        break;
      }
    }
    break;
  }    
}

/**
 * @brief  This function is called attribute value corresponding to 
 *         ledButtonCharHandle characteristic gets modified.
 * @param  Handle of the attribute
 * @param  Size of the modified attribute data
 * @param  Pointer to the modified attribute data
 * @retval None
 */
void Attribute_Modified_CB(uint16_t handle, uint8_t data_length, uint8_t *att_data)
{
 
}
/**
 * @}
 */
 
/**
 * @}
 */

/**
 * @}
 */

 /**
 * @}
 */
 
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
